/**
 * Title: 系统
 * Description: sGateService
 * Company:心医国际数字医疗系统（大连） 有限公司
 * Copyright (c) 2016, 2017, Senyint. All rights reserved.
 * @author WangNaiFei
 * @version 1.0
 */

package com.senyint.sys.utils;

import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

/**
 * {@code MapUtils}类
 * <p>
 * 
 * @author WangNaiFei, WangNaiFei@senyint.com
 * @date 2017年3月27日 下午10:20:34
 * @version 1.0
 * @since jdk1.7+
 */

public class MapUtils {

	public static final String REQUEST_ARRAY_PARAM_NAMES = "REQUEST_ARRAY_PARAM_NAMES";

	/**
	 * 深度克隆map<br>
	 * 注:map 必须可序列化
	 * <p>
	 * 
	 * @author WangNaiFei, WangNaiFei@senyint.com
	 * @date 2017年3月28日 上午9:39:14
	 * @version 1.0
	 * @param map
	 * @see CloneUtils
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static HashMap clone(HashMap map) {
		return CloneUtils.clone(map);
	}

	/**
	 * 根据xpath获取map的子值
	 * <p>
	 * 
	 * @author WangNaiFei, WangNaiFei@senyint.com
	 * @date 2017年3月28日 上午9:38:50
	 * @version 1.0
	 * @param xpath
	 * @param map
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static Object getMapValueByXpath(String xpath, Map map) throws Exception {
		xpath = xpath.replaceAll("\\\\", "/");
		String[] split = xpath.split("/");
		Object temp = map;
		for (String key : split) {
			int indexStart = -1, indexEnd = -1, index = -1;
			boolean isMap = true;
			do {
				indexStart = key.indexOf("[", indexStart + 1);
				if (indexStart != -1) {
					if (temp instanceof Map) {
						String tkey = key.substring(0, indexStart);
						temp = ((Map) temp).get(tkey);
					}
					indexEnd = key.indexOf("]", indexEnd);
					index = Integer.parseInt(key.substring(indexStart + 1, indexEnd));
					temp = ((List) temp).get(index);
					isMap = false;
				}
			} while (indexStart != -1);
			if (isMap) {
				temp = ((Map) temp).get(key);
			}
		}
		return temp;
	}

	/**
	 * 根据xpath设置map的子值
	 * <p>
	 * 
	 * @author WangNaiFei, WangNaiFei@senyint.com
	 * @date 2017年3月28日 上午9:38:50
	 * @version 1.0
	 * @param xpath targetValue map
	 * @param map
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void setMapValueByXpath(String xpath, Object targetValue, Map map) throws Exception {
		Object value = MapUtils.getMapValueByXpath(xpath, map);
		if (!(value instanceof Map) && !(value instanceof List)) {
			if (xpath.lastIndexOf(']') == xpath.length() - 1) {
				List temp = (List) MapUtils.getMapValueByXpath(xpath.substring(0, xpath.lastIndexOf('[')), map);
				for (int i = 0; i < temp.size(); i++) {
					if (temp.get(i).equals(value)) {
						temp.remove(i);
						temp.add(i, targetValue);
					}
				}
			} else if (xpath.indexOf('/') > 0) {
				String tempXpath = xpath.substring(0, xpath.lastIndexOf('/'));
				Map temp = (Map) MapUtils.getMapValueByXpath(tempXpath, map);
				temp.put(xpath.substring(xpath.lastIndexOf('/') + 1), targetValue);
			} else {
				map.put(xpath, targetValue);
			}
		} else {
			throw new RuntimeException("需要修改的节点不是最终节点不支持修改");
		}
	}

	/**
	 * @Title: requestParamToMap
	 * @Description: 请求中数据转Map<String,String>
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年9月27日 下午2:25:23
	 * @version 1.0
	 * @param request
	 * @return
	 * @see 得不到请求中的数组数据 Enumeration.hasMoreElements
	 */
	public static Map<String, String> requestParamToMap(HttpServletRequest request) {
		Enumeration<String> parameterNames = request.getParameterNames();
		Map<String, String> r = new HashMap<String, String>();
		while (parameterNames.hasMoreElements()) {
			String key = parameterNames.nextElement();
			r.put(key, request.getParameter(key));
		}
		return r;
	}

	/**
	 * @Title: requestParamToMapObject
	 * @Description: 请求中数据转Map
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年9月27日 下午2:24:56
	 * @version 1.0
	 * @param request
	 * @param arraykey
	 * @return
	 */
	public static Map<String, Object> requestParamToMapObject(HttpServletRequest request, String... arraykey) {
		Enumeration<String> parameterNames = request.getParameterNames();
		Map<String, Object> r = new HashMap<String, Object>();
		List<String> kl = Arrays.asList(arraykey);
		while (parameterNames.hasMoreElements()) {
			String key = parameterNames.nextElement();
			if (kl.contains(key) && !r.containsKey(key)) {
				r.put(key, request.getParameterValues(key));
			} else {
				r.put(key, request.getParameter(key));
			}
		}
		return r;
	}

	/**
	 * @Title: requestParamToMapObject
	 * @Description: 请求中数据转Map
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年9月27日 下午2:24:52
	 * @version 1.0
	 * @param request
	 * @return
	 */
	public static Map<String, Object> requestParamToMapObjectDefaultArrayKey(HttpServletRequest request) {
		String[] parameterValues = request.getParameterValues(REQUEST_ARRAY_PARAM_NAMES);
		if (parameterValues == null) {
			return requestParamToMapObject(request);
		} else {
			return requestParamToMapObject(request, parameterValues);
		}
	}

}
